{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 装饰器可以让其他函数在不需要做任何代码变动的前提下增加额外功能\n",
    "**装饰器的返回值是一个函数对象**  \n",
    "* 有了装饰器，我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def add(a, b):\n",
    "    res = a + b\n",
    "    return res"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **计算加法(add)的时间**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "此函数的执行时间： 0.0\n"
     ]
    }
   ],
   "source": [
    "def add(a, b):\n",
    "    start_time = time.time()\n",
    "    res = a + b\n",
    "    exec_time = time.time() - start_time\n",
    "    print(\"此函数的执行时间：\", exec_time)\n",
    "    return res\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    add(3,6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **计算减法函数（sub）的时间**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "此函数的执行时间： 0.0\n"
     ]
    }
   ],
   "source": [
    "def sub(a, b):\n",
    "    start_time = time.time()\n",
    "    res = a - b\n",
    "    exec_time = time.time() - start_time\n",
    "    print(\"此函数的执行时间：\", exec_time)\n",
    "    return res\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    sub(3,6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **计算时间的代码需要改动，每个函数都要改动，所以需要引入装饰器**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "def time_calc(func):# 如果加法使用这个装饰器，那个func = add\n",
    "    def wrapper(*args):# 上面是调用的函数，这里传入的则是函数的参数，所以要设为*args\n",
    "        start_time = time.time()\n",
    "        result = func(*args)\n",
    "        exec_time = time.time() - start_time\n",
    "        return result# 返回值为调用函数的值，得到的结果再返回\n",
    "    return wrapper\n",
    "\n",
    "# 使用装饰器\n",
    "@time_calc\n",
    "def add(a, b):\n",
    "    return a+b\n",
    "\n",
    "@time_calc\n",
    "def sub(a, b):\n",
    "    return a-b\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    print(add(3,5))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **要使用某个类的方法，需要先实例化一个对象再调用方法**  \n",
    "    * 而使用$@staticmethod$或$@classmethod$，就可以不需要实例化，直接类名.方法名()来调用\n",
    "* $@staticmethod$不需要表示自身对象的self和自身类的cls参数，就跟使用函数一样\n",
    "* $@classmethod$也不需要self参数，但第一个参数需要是表示自身类的cls参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "foo\n",
      "static_foo\n",
      "class_foo\n"
     ]
    }
   ],
   "source": [
    "class A():  \n",
    "    def __init__(self, bar, name):\n",
    "        self.bar = bar\n",
    "        self.name = name   \n",
    "        \n",
    "\n",
    "    def foo(self):  \n",
    "        print ('foo')\n",
    "\n",
    "    @staticmethod  \n",
    "    def static_foo():  \n",
    "        print ('static_foo')\n",
    "\n",
    "    @classmethod  \n",
    "    def class_foo(cls):  \n",
    "        print ('class_foo') \n",
    "    \n",
    "#     @classmethod\n",
    "#     def class_test(cls):\n",
    "#         print(\"class_test\")\n",
    "#         return cls(199)\n",
    "\n",
    "a = A(100, 300)\n",
    "a.foo()\n",
    "A.static_foo()  \n",
    "A.class_foo()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# yield\n",
    "* 把一个函数变成一个生成器\n",
    "* 起到一个延迟的作用，在需要的时候产生结果，节省资源\n",
    "* 声明一个序列不同的生成器，在不使用的情况下不占内存，当列表很大时候  \n",
    "* **generator会按需产生(通过next()方法)，不会一次性生成所有数据**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "def get_Num(n):\n",
    "    i = 0\n",
    "    while i <= n:\n",
    "\n",
    "        i += 1\n",
    "        yield i  #不是赋值，得到的结果是一个生成器\n",
    "        \n",
    "f = get_Num(5)\n",
    "\n",
    "print(next(f))\n",
    "print(next(f))\n",
    "print(next(f))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
